function getLocalGist() {
    let gist = JSON.parse(localStorage.getItem("gistInfo"));
    if (gist == null) {
        gist = {
            name: "bookmarkArray.json",
            description: "浏览器书签同步数据",
            routerStack: ["accountLogin"],
            interval: 600,
            id: "",
            username: "",
            password: "",
            passwordRepeat: "",
            access_token: "",
            updateTime: "",
            autoSync: false,
            autoUpload: false,
            autoDownload: false,
            from: "",
            status: false,
            isRegist: false,
            encrypted: "",
            first: true,
            noticeList: [],
            noticeRead: {},
        }
        localStorage.setItem("gistInfo", JSON.stringify(gist));
    }
    return gist;
}

function setLocalGist(obj) {
    let gist = getLocalGist();
    for (let key in obj) {
        gist[key] = obj[key];
    }
    localStorage.setItem("gistInfo", JSON.stringify(gist));
}

function deleteLocalGistAttribute(key) {
    let gist = getLocalGist();
    delete gist[key];
    localStorage.setItem("gistInfo", JSON.stringify(gist));
}

/**
 * 创建代码段片段
 * @param {object} files 代码段内容
 * @param {function} callback 
 */
function createGists(files, callback) {
    let gist = getLocalGist();
    new Ajax({
        url: "https://gitee.com/api/v5/gists",
        method: "post",
        header: {
            "Content-type": "application/json"
        },
        data: {
            access_token: gist.access_token,
            files: {
                [gist.name]: {
                    content: JSON.stringify(files, undefined, 4)
                }
            },
            description: gist.description
        }
    }, (err, body) => {
        try {
            let res = JSON.parse(body);
            let info = JSON.parse(res.files[gist.name].content);
            callback(err, info, res);
        }
        catch (err) {
            callback(body);
        }
    });
}

/**
 * 根据id获取代码段片段
 * @param {function} callback 
 */
function getGists(callback) {
    let gist = getLocalGist();
    new Ajax({
        url: `https://gitee.com/api/v5/gists/${gist.id}`,
        data: {
            access_token: gist.access_token,
            id: gist.id
        }
    }, (err, body) => {
        try {
            let res = JSON.parse(body);
            let info = JSON.parse(res.files[gist.name].content);
            callback(err, info, res);
        }
        catch (err) {
            callback(body);
        }
    });
}

/**
 * 修改代码片段
 * @param {object} files 更新后的内容
 * @param {function} callback 
 */
function editGist(files, callback) {
    let gist = getLocalGist();
    new Ajax({
        url: `https://gitee.com/api/v5/gists/${gist.id}`,
        method: "patch",
        header: {
            "Content-type": "application/json"
        },
        data: {
            id: gist.id,
            access_token: gist.access_token,
            files: {
                [gist.name]: {
                    content: JSON.stringify(files, undefined, 4)
                }
            },
            description: gist.description
        }
    }, (err, body) => {
        try {
            let res = JSON.parse(body);
            let info = JSON.parse(res.files[gist.name].content);
            callback(err, info, res);
        }
        catch (err) {
            callback(body);
        }
    });
}

/**
 * 创建同步，如果传入了id则会同步此id，未传id则会创建一个新的记录
 * @param {string} access_token 私人令牌
 * @param {string} [id] 代码片段id
 */
function createSync(access_token, id, callback) {
    if (id && getLocalGist().id == id) {
        return callback(null, true);
    }
    setLocalGist({ access_token: access_token });
    Thenjs(updateLocalStorage => {
        if (id) {
            setLocalGist({ id: id });
            getGists((err, info, res) => {
                updateLocalStorage(err, info, res, true);
            });
        }
        else {
            Thenjs(cont => {
                chrome.bookmarks.getSubTree("1", function (bookmarkArray) {
                    cont(null, bookmarkArray);
                });
            }).then((cont, bookmarkArray) => {
                createGists({
                    updateTime: new Date().getTime(),
                    bookmarkArray: bookmarkArray
                }, (err, info, res) => {
                    updateLocalStorage(err, info, res, false);
                });
            });
        }
    }).then((cont, info, res, flag) => {
        setLocalGist({
            id: res.id,
            updateTime: info.updateTime,
            status: true,
            first: false,
        });
        if (flag) {
            setBookmark(info.bookmarkArray);
        }
        callback(null, true);
    }).fail((cont) => {
        callback(null, false);
    });
}

/**
 * 设置书签
 * @param {array} bookmarkArray 
 */
function setBookmark(bookmarkArray) {
    if (bookmarkArray.length == 0) {
        return;
    }
    Thenjs(cont => {
        chrome.bookmarks.getSubTree("1", function (lastBookmarkArray) {
            cont(null, lastBookmarkArray);
        });
    }).then((cont, lastBookmarkArray) => {
        setLocalGist({ lastBookmarkArray: lastBookmarkArray });
        Thenjs.each(lastBookmarkArray[0].children, (cont, item) => {
            // 删除当前所有书签
            chrome.bookmarks.removeTree(item.id, () => {
                cont();
            });
        }).then(() => {
            function create(stack) {
                Thenjs.each(stack.pop(), (cont, item) => {
                    delete item.id;
                    delete item.dateAdded;
                    delete item.dateGroupModified
                    let children = item.children;
                    delete item.children;
                    chrome.bookmarks.create(item, (bookmark) => {
                        if (children) {
                            children.forEach(item => {
                                item.parentId = bookmark.id;
                            });
                            stack.push(children);
                        }
                        cont();
                    });
                }).then(cont => {
                    if (stack.length > 0) {
                        create(stack);
                    }
                });;
            }
            create([bookmarkArray[0].children]);
        })
    });
}

/**
 * 上传本地书签
 * @param {function} callback 
 */
function upload(callback) {
    Thenjs(cont => {
        chrome.bookmarks.getSubTree("1", function (bookmarkArray) {
            cont(null, bookmarkArray);
        });
    }).then((cont, bookmarkArray) => {
        editGist({
            updateTime: new Date().getTime(),
            bookmarkArray: bookmarkArray
        }, (err, info) => {
            setLocalGist({ updateTime: info.updateTime });
            if (callback) {
                callback(info.updateTime);
            }
        });
    });
}

/**
 * 同步云端书签
 * @param {function} callback 
 */
function download(callback) {
    console.log("download");
    Thenjs((cont) => {
        getGists(cont);
    }).then((cont, info) => {
        if (info.updateTime > getLocalGist().updateTime) {
            setLocalGist({
                updateTime: info.updateTime,
                from: "云端"
            });
            cont(null, info.bookmarkArray);
        }
        else {
            if (callback) {
                callback("无需更新！", getLocalGist().updateTime);
            }
        }
    }).then((cont, bookmark) => {
        setBookmark(bookmark);
        if (callback) {
            callback("已更新", getLocalGist().updateTime);
        }
    });
}

/**
 * 加密
 * @param {string} data 需要加密的数据
 * @param {string} iv 加密向量
 * @param {string} key 秘钥
 */
function encrypt(data, iv, key) {
    return CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(key), {
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    }).toString();
}

/**
 * 解密
 * @param {string} encrypted 需要解密的数据
 * @param {string} iv 解密向量
 * @param {string} key 秘钥
 */
function decrypt(encrypted, iv, key) {
    return CryptoJS.AES.decrypt(encrypted, CryptoJS.enc.Utf8.parse(key), {
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    }).toString(CryptoJS.enc.Utf8);
}
